package von.seiji.cn.thread;


import org.junit.Test;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: SeiJi
 * @DateTime: 2022/2/8 9:46
 * @Description: 此人很懒，未写描述！
 **/
public class T1 {

    Integer num = new Integer(0);

    Integer num1 = new Integer(0);

    IntegerHelper helper = new IntegerHelper(0);

    AtomicInteger num0 = new AtomicInteger(0);

    /**
     * LOCK
     * @throws InterruptedException
     */
    @Test
    public void test() throws InterruptedException {

        long l = System.currentTimeMillis();

        final int THREAD_SIZE = 10;

        final int TASK_SIZE = 100000;

        CountDownLatch latch = new CountDownLatch(THREAD_SIZE);

        Object lock = new Object();

        for (int i = 0; i < THREAD_SIZE; i++) {


            new Thread(() -> {
                for (int j = 0; j < TASK_SIZE / THREAD_SIZE; j++) {

                    synchronized (lock) {

                        num++;

                    }
                }
                latch.countDown();
            }).start();

        }

        latch.await();
        System.out.println("num-->" + num);

        System.out.println("consumer time : " + (System.currentTimeMillis() - l) + "ms");

    }


    /**
     * reflect
     * @throws InterruptedException
     */
    @Test
    public void test1() throws InterruptedException {
        long l = System.currentTimeMillis();

        final int THREAD_SIZE = 10;

        final int TASK_SIZE = 100000;

        CountDownLatch latch = new CountDownLatch(THREAD_SIZE);

        for (int i = 0; i < THREAD_SIZE; i++) {

            Thread thread = new Thread(() -> {
                for (int j = 0; j < TASK_SIZE / THREAD_SIZE; j++) {

                    synchronized (num1) {
                        try {
                            Field value = Integer.class.getDeclaredField("value");
                            value.setAccessible(true);
                            value.set(num1, num1 + 1);
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                        }
                    }

                }
                latch.countDown();
            });
            thread.start();

        }

        latch.await();

        System.out.println("num1-->" + num1);

        System.out.println("consumer time : " + (System.currentTimeMillis() - l) + "ms");

    }

    /**
     * AtomicInteger
     * @throws InterruptedException
     */
    @Test
    public void test0() throws InterruptedException {
        long l = System.currentTimeMillis();

        final int THREAD_SIZE = 10;

        final int TASK_SIZE = 100000;

        CountDownLatch latch = new CountDownLatch(THREAD_SIZE);

        for (int i = 0; i < THREAD_SIZE; i++) {

            new Thread(() -> {
                for (int j = 0; j < TASK_SIZE / THREAD_SIZE; j++) {

                    synchronized (num0) {
                        num0.incrementAndGet();

                    }

                }
                latch.countDown();
            }).start();

        }

        latch.await();
        System.out.println("num0-->" + num0);

        System.out.println("consumer time : " + (System.currentTimeMillis() - l) + "ms");

    }

    /**
     * Object prop
     * @throws InterruptedException
     */
    @Test
    public void test999() throws InterruptedException {
        long l = System.currentTimeMillis();

        final int THREAD_SIZE = 10;

        final int TASK_SIZE = 100000;

        CountDownLatch latch = new CountDownLatch(THREAD_SIZE);

        for (int i = 0; i < THREAD_SIZE; i++) {

            new Thread(() -> {
                for (int j = 0; j < TASK_SIZE / THREAD_SIZE; j++) {

                    synchronized (helper) {

                        helper.increment();

                    }

                }
                latch.countDown();
            }).start();

        }

        latch.await();
        System.out.println("num-->" + helper.getNum());

        System.out.println("consumer time : " + (System.currentTimeMillis() - l) + "ms");

    }
}

class IntegerHelper {
    int num;

    public IntegerHelper(int num) {
        this.num = num;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void increment() {
        this.num++;
    }
}
